package com.xiguthings.waka.web.controller.sysfile;

import java.io.*;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.alibaba.fastjson.JSONObject;
import com.xiguthings.waka.dao.DataBaseStatus;
import com.xiguthings.waka.exception.BussinessException;
import com.xiguthings.waka.exception.HttpSendErrorException;
import com.xiguthings.waka.po.Paper;
import com.xiguthings.waka.po.PaperExample;
import com.xiguthings.waka.po.SysFile;
import com.xiguthings.waka.po.SysFileExample;
import com.xiguthings.waka.publicUtils.HttpUtils;
import com.xiguthings.waka.publicUtils.PropertiesUtil;
import com.xiguthings.waka.publicUtils.StringUtils;
import com.xiguthings.waka.web.controller.paper.PaperVo;
import org.apache.commons.fileupload.disk.DiskFileItem;
import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.xiguthings.waka.service.sysfile.ISysFileService;
import com.xiguthings.waka.web.controller.base.AbstractController;
import com.xiguthings.waka.web.controller.base.ResponseEntity;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import springfox.documentation.annotations.ApiIgnore;

@Controller
@RequestMapping("/sysfile")
@Api(tags = "文件")
public class SysFileController extends AbstractController {
    @Resource
    private ISysFileService sysFileService;

    @Value("${waka_server.ip_port}")
    private String wakaServerIP;

    public SysFileController() {
        super();
        logger.debug("waka服务器的ip地址是：{}", wakaServerIP);
    }

    /**
     * 创建查询条件
     *
     * @param sysFileVo
     * @param example
     * @throws NumberFormatException
     */
    private void queryConditions(SysFileVo sysFileVo, SysFileExample example) throws NumberFormatException {

        SysFileExample.Criteria criteria = example.createCriteria();
        // 如果查询条件为空的
        if (sysFileVo == null) {
            // 则查询所有未被删除的
            criteria.andStatusNotEqualTo(DataBaseStatus.DELETE);
            return;
        }

        // 如果有查询条件
        SysFile sysFile = sysFileVo.getSysFile();
        // 添加查询条件
        if (sysFile != null) {
            if (StringUtils.isNotBlank(sysFile.getFileId())) {
                criteria.andFileIdEqualTo(sysFile.getFileId());
            }
            if (StringUtils.isNotBlank(sysFile.getRelationId())) {
                criteria.andRelationIdEqualTo(sysFile.getRelationId());
            }
            if (StringUtils.isNotBlank(sysFile.getModuleCode())) {
                criteria.andModuleCodeEqualTo(sysFile.getModuleCode());
            }

        }

        if (StringUtils.isNotBlank(sysFileVo.getInStatus())) {
            // 添加包含的状态
            String statuses = sysFileVo.getInStatus();
            String[] statusArr = statuses.split(",");
            List<Integer> statusList = new ArrayList<>();
            for (String str : statusArr) {
                statusList.add(new Integer(str));
            }
            criteria.andStatusIn(statusList);
        } else {
            // 如果状态的查询条件是空的，则查询没有被删除的
            criteria.andStatusNotEqualTo(DataBaseStatus.DELETE);
        }

    }


    @ApiOperation(tags = {"1.控制台",
            "2.用户端"}, value = "查询详情", httpMethod = "GET", notes = "fileId可以直接查询(返回的data对象就是file对应的对象)，或者选择使用relationId和moduleCode进行组合查询(返回的data对象是file对应的对象集合)", response = ResponseEntity.class)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "sysFile.fileId", value = "主键id", dataType = "String", required = false, paramType = "query"),
            @ApiImplicitParam(name = "sysFile.relationId", value = "关联的对象的ID", dataType = "String", required = false, paramType = "query"),
            @ApiImplicitParam(name = "sysFile.moduleCode", value = "模块的代码", dataType = "String", required = false, paramType = "query")})
    @RequestMapping("/detail")
    @ResponseBody
    public ResponseEntity detail(@ApiIgnore SysFileVo sysFileVo) throws Exception {
        if (sysFileVo == null
                || sysFileVo.getSysFile() == null
                || StringUtils.isBlank(sysFileVo.getSysFile().getFileId())) {
            BussinessException.throwThis(CODE_EMPTY_REQUIRED, "sysFile.fileId不能为空");
        }

        String id = sysFileVo.getSysFile().getFileId();
        SysFile sysFile = sysFileService.selectByPrimaryKey(id);
        return ajaxReturnMap(CODE_SUCCESS, "", sysFile);
    }

    @ApiOperation(tags = {"1.控制台",
            "2.用户端"}, value = "下载文件", httpMethod = "GET", notes = "请指明fileId，或则根据 sysFile.relationId、sysFile.moduleCode进行组合,当组合查询出现多个文件的情况，默认返回查询到的第一个文件")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "sysFile.fileId", value = "主键id", dataType = "String", required = false, paramType = "query"),
            @ApiImplicitParam(name = "sysFile.relationId", value = "关联的对象的ID", dataType = "String", required = false, paramType = "query"),
            @ApiImplicitParam(name = "sysFile.moduleCode", value = "模块的代码", dataType = "String", required = false, paramType = "query")})
    @RequestMapping("/download")
    public String download(@ApiIgnore SysFileVo sysFileVo, @ApiIgnore HttpServletResponse response) throws Exception {
        if (sysFileVo == null
                || sysFileVo.getSysFile() == null) {
            BussinessException.throwThis(CODE_EMPTY_REQUIRED, "sysFile.relationId、sysFile.moduleCode不能为空");
        }
        SysFile sysFile = sysFileVo.getSysFile();
        String fileId = sysFile.getFileId();
        String relationId = sysFile.getRelationId();
        String moduleCode = sysFile.getModuleCode();
        if (StringUtils.isBlank(fileId) && StringUtils.isBlank(relationId) && StringUtils.isBlank(moduleCode)) {
            BussinessException.throwThis(CODE_EMPTY_REQUIRED, " 请指明fileId，或则根据 sysFile.relationId、sysFile.moduleCode进行查询");
        }

        SysFile fileEntity = null;
        if (StringUtils.isNotBlank(fileId)) {
            // 根据ID查询
            fileEntity = sysFileService.selectByPrimaryKey(fileId);
        } else if (StringUtils.isNotBlank(relationId) || StringUtils.isNotBlank(moduleCode)) {
            // 根据组合查询
            SysFileExample example = new SysFileExample();
            SysFileExample.Criteria criteria = example.createCriteria();
            if (StringUtils.isNotBlank(relationId)) {
                criteria.andRelationIdEqualTo(sysFile.getRelationId());
            }
            if (StringUtils.isNotBlank(moduleCode)) {
                criteria.andModuleCodeEqualTo(sysFile.getModuleCode());
            }
            List<SysFile> list = sysFileService.selectByExample(example);
            // 如果大于1个文件 , 默认选择第一个
            if (list == null && list.size() > 0) {
                fileEntity = list.get(0);
            }
        }

        if (fileEntity == null) {
            throwHttpSendErrorExceptionException(500, "找不到下载资源");
        }

        response.setContentType("octets/stream");
        response.addHeader("Content-Type", "text/html; charset=utf-8");

        DataInputStream dataInputStream = null;
        ByteArrayOutputStream output = null;
        URL url = new URL(wakaServerIP + "/sysfile/download?sysFile.fileId=" + fileEntity.getFileId());
        try {
            dataInputStream = new DataInputStream(url.openStream());
            output = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int length;
            while ((length = dataInputStream.read(buffer)) > 0) {
                output.write(buffer, 0, length);
            }
            OutputStream os = response.getOutputStream();
            byte[] context = output.toByteArray();
            os.write(context);
        } catch (Exception e) {
            throw e;
        } finally {
            if (output != null) {
                try {
                    output.close();
                } catch (IOException e) {
                    logErr(e);
                }
            }
            if (dataInputStream != null) {
                try {
                    dataInputStream.close();
                } catch (IOException e) {
                    logErr(e);
                }
            }
        }
        super.setResponseToOpen(response);
        return null;
    }

    @ApiOperation(tags = {"1.控制台",
            "2.用户端"}, value = "上传文件", httpMethod = "GET", notes = "上传文件后，必须进行文件关联(即访问接口 /sysfile/relation )，否则文件会被服务器清理，将无法再找回", response = ResponseEntity.class)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "file", value = "需要上传的文件(数组)", dataType = "file", required = true),
            @ApiImplicitParam(name = "sysFile.relationId", value = "关联对象的主键", dataType = "string", required = false, paramType = "query"),
            @ApiImplicitParam(name = "sysFile.moduleCode", value = "模块代码", dataType = "string", required = false, paramType = "query"),
    })
    @RequestMapping(value = "/upload", method = RequestMethod.POST)
    @ResponseBody
    public JSONObject upload(@ApiIgnore HttpServletRequest request,
                             @ApiIgnore HttpServletResponse response,
                             @ApiIgnore SysFileVo sysFileVo,
                             @ApiIgnore @RequestParam(value = "file") MultipartFile file) throws Exception {


        if (file == null) {
            HttpSendErrorException.throwThis(500, "未选择要上传的文件");
        }

        String relationId = null;
        String moduleCode = null;
        if (sysFileVo != null
                && sysFileVo.getSysFile() != null) {
            SysFile sysFile = sysFileVo.getSysFile();
            relationId = sysFile.getRelationId();
            moduleCode = sysFile.getModuleCode();
        }

        HashMap<String, File> files = new HashMap<>();
        File f = null;
        try {
            f = File.createTempFile(StringUtils.getRandomUUID(), FilenameUtils.getExtension(file.getOriginalFilename()));
            file.transferTo(f);
            //在程序退出时删除临时文件
            f.deleteOnExit();
        } catch (Exception e) {
            e.printStackTrace();
        }
        files.put("file", f);
        String resStr = HttpUtils.sendPost(wakaServerIP + "/sysfile/upload?sysFile.relationId=" + relationId + "&sysFile.moduleCode=" + moduleCode, null, null, files, null, null);
        JSONObject resJson = JSONObject.parseObject(resStr);

        response.setContentType("text/plain;charset=utf-8");
        super.setResponseToOpen(response);
        return resJson;
    }

    @ApiOperation(tags = {"1.控制台"}, value = "文件关联", httpMethod = "GET", notes = "sysFile.fileId、sysFile.relationId、sysFile.moduleCode都是必填参数", response = ResponseEntity.class)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "sysFile.fileId", value = "主键id", dataType = "String", required = true, paramType = "query"),
            @ApiImplicitParam(name = "sysFile.relationId", value = "关联的对象的ID", dataType = "String", required = true, paramType = "query"),
            @ApiImplicitParam(name = "sysFile.moduleCode", value = "模块的代码", dataType = "String", required = true, paramType = "query")})
    @RequestMapping("/relation")
    @ResponseBody
    public ResponseEntity relation(@ApiIgnore SysFileVo sysFileVo) throws Exception {
        if (sysFileVo == null
                || sysFileVo.getSysFile() == null
                || StringUtils.isBlank(sysFileVo.getSysFile().getFileId())
                || StringUtils.isBlank(sysFileVo.getSysFile().getRelationId())
                || StringUtils.isBlank(sysFileVo.getSysFile().getModuleCode())) {
            BussinessException.throwThis(CODE_EMPTY_REQUIRED, "必填参数不能为空；sysFile.fileId、sysFile.relationId、sysFile.moduleCode都是必填参数");
        }

        SysFile sysFile = new SysFile();
        sysFile.setFileId(sysFileVo.getSysFile().getFileId());
        sysFile.setRelationId(sysFileVo.getSysFile().getRelationId());
        sysFile.setModuleCode(sysFileVo.getSysFile().getModuleCode());

        sysFileService.updateByPrimaryKeySelective(sysFile);
        return ajaxReturnMap(CODE_SUCCESS, "更新关联成功", sysFile.getFileId());
    }

    @ApiOperation(tags = {"1.控制台"}, value = "删除文件资源", httpMethod = "GET", notes = "请指明sysFile.fileId，或则根据 sysFile.relationId、sysFile.moduleCode进行组合删除", response = ResponseEntity.class)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "sysFile.fileId", value = "主键id", dataType = "String", required = false, paramType = "query")
//            @ApiImplicitParam(name = "sysFile.relationId", value = "关联的对象的ID", dataType = "String", required = false, paramType = "query"),
//            @ApiImplicitParam(name = "sysFile.moduleCode", value = "模块的代码", dataType = "String", required = false, paramType = "query")
    })
    @ResponseBody
    @RequestMapping("/delete")
    public ResponseEntity delete(@ApiIgnore SysFileVo sysFileVo) throws Exception {
        if (sysFileVo == null
                || sysFileVo.getSysFile() == null) {
            BussinessException.throwThis(CODE_EMPTY_REQUIRED, "sysFile.relationId、sysFile.moduleCode不能为空");
        }
        SysFile sysFile = sysFileVo.getSysFile();
        String fileId = sysFile.getFileId();
        if (StringUtils.isBlank(fileId)) {
            BussinessException.throwThis(CODE_EMPTY_REQUIRED, " 请指明fileId");
        }
        int row = sysFileService.deleteByPrimaryKey(fileId);
        if (row > 0) {
            return ajaxReturnMap(CODE_SUCCESS, "删除文件成功", null);
        } else {
            return ajaxReturnMap(CODE_FAULT, "删除文件失败", null);
        }

    }


    @ApiOperation(tags = {"1.控制台"}, value = "获取文件列表", httpMethod = "GET", notes = "", response = ResponseEntity.class)
    @ApiImplicitParams({
//            @ApiImplicitParam(name = "sysFile.fileId", value = "主键id", dataType = "String", required = false, paramType = "query"),
            @ApiImplicitParam(name = "sysFile.relationId", value = "关联的对象的ID", dataType = "String", required = false, paramType = "query"),
            @ApiImplicitParam(name = "sysFile.moduleCode", value = "模块的代码", dataType = "String", required = false, paramType = "query")
    })
    @ResponseBody
    @RequestMapping("/list")
    public ResponseEntity list(@ApiIgnore SysFileVo sysFileVo) throws Exception {
        if (sysFileVo == null
                || sysFileVo.getSysFile() == null
                || StringUtils.isBlank(sysFileVo.getSysFile().getRelationId())) {
            return ajaxReturnMap(CODE_SUCCESS, null, null);
        }

        SysFileExample example = new SysFileExample();
        queryConditions(sysFileVo, example);
        List<SysFile> list = sysFileService.selectByExample(example);
        return ajaxReturnMap(CODE_SUCCESS, null, list);
    }

    @ApiOperation(tags = {"1.控制台"}, value = "更新文件状态", httpMethod = "GET", notes = "", response = ResponseEntity.class)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "status", value = "状态", dataType = "int", required = true, paramType = "query"),
            @ApiImplicitParam(name = "fileId", value = "文件id", dataType = "String", required = true, paramType = "query")
    })
    @ResponseBody
    @RequestMapping("/updatestatus")
    public ResponseEntity updatestatus(@ApiIgnore Integer status, String fileId) throws Exception {
        if (status == null || StringUtils.isBlank(fileId)) {
            BussinessException.throwThis(CODE_EMPTY_REQUIRED, "无法操作空参数");
        }

        SysFile file = new SysFile();
        file.setStatus(status);
        file.setFileId(fileId);
        sysFileService.updateByPrimaryKey(file);
        return ajaxReturnMap(CODE_SUCCESS, "更新成功", file.getFileId());
    }
}
